﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Data.SqlClient;
using SmoLiteApi.Sql;
using SmoLiteApi.Helper;

namespace SmoLiteApi
{
    /// <summary/>
    public class ViewCollection : IEnumerable<View>
    {
        private Database _database;

        /// <summary/>
        internal ViewCollection(Database database)
        {
            this._database = database;
        }

        /// <summary/>
        public View this[string name, string schemaName]
        {
            get
            {
                // get the list
                List<View> storedProcedures = this.FetchObjects(name, schemaName);

                // return the data
                if (storedProcedures.Count == 0)
                {
                    return null;
                }

                // return the one and only
                return storedProcedures[0];
            }
        }

        /// <summary/>
        public IEnumerator<View> GetEnumerator()
        {
            return this.FetchObjects(null, null).GetEnumerator();
        }

        /// <summary/>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.FetchObjects(null, null).GetEnumerator();
        }

        /// <summary/>
        private List<View> FetchObjects(
            string name,
            string schemaName)
        {
            List<View> views = new List<View>();

            ViewSelectSql viewSelectSql = new ViewSelectSql();

            // set attributes
            viewSelectSql.AddObject(new { Name = name, Schema = schemaName });

            using (SqlCommandHelper sqlCommandHelper = SqlCommandHelper.FetchSqlCommand(this._database.SqlConnection, viewSelectSql.Render()))
            {
                using (SqlDataReader sqlDataReader = sqlCommandHelper.ExecuteReader())
                {
                    while (sqlDataReader.Read())
                    {
                        View view = new View(
                            this._database,
                            sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_NAME)),
                            sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_SCHEMA)),
                            sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_TEXT)));

                        // add to the list
                        views.Add(view);
                    }
                }
            }

            ViewIndexSelectSql viewIndexSelectSql = new ViewIndexSelectSql();

            // set attributes
            viewIndexSelectSql.AddObject(new { Name = name, Schema = schemaName });

            using (SqlCommandHelper sqlCommandHelper = SqlCommandHelper.FetchSqlCommand(this._database.SqlConnection, viewIndexSelectSql.Render()))
            {
                using (SqlDataReader sqlDataReader = sqlCommandHelper.ExecuteReader())
                {
                    while (sqlDataReader.Read())
                    {
                        View view = views.Find(value =>
                            value.Name == sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_VIEW)) &&
                            value.Schema == sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_SCHEMA)));

                        Index index = view.Indexes[
                            sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_NAME))];

                        // has the key been created
                        if (index == null)
                        {
                            // create it
                            index = new Index(
                                sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_NAME)));

                            // set attributes
                            index.FillFactor = sqlDataReader.GetByte(sqlDataReader.GetOrdinal(Constant.PARAMETER_FILL_FACTOR));
                            index.IsPrimaryKey = sqlDataReader.GetBoolean(sqlDataReader.GetOrdinal(Constant.PARAMETER_IS_PRIMARY_KEY));
                            index.IsClustered = sqlDataReader.GetBoolean(sqlDataReader.GetOrdinal(Constant.PARAMETER_IS_CLUSTERED));
                            index.IsUnique = sqlDataReader.GetBoolean(sqlDataReader.GetOrdinal(Constant.PARAMETER_IS_UNIQUE));
                            index.PadIndex = sqlDataReader.GetBoolean(sqlDataReader.GetOrdinal(Constant.PARAMETER_IS_PADDED));

                            // add it
                            view.Indexes.Add(index);
                        }

                        IndexedColumn indexedColumn = new IndexedColumn(
                            sqlDataReader.GetByte(sqlDataReader.GetOrdinal(Constant.PARAMETER_KEY_ORDINAL)),
                            sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_COLUMN)));

                        // set attributes
                        indexedColumn.Descending = sqlDataReader.GetBoolean(sqlDataReader.GetOrdinal(Constant.PARAMETER_IS_DESCENDING_KEY));
                        indexedColumn.IsIncluded = sqlDataReader.GetBoolean(sqlDataReader.GetOrdinal(Constant.PARAMETER_IS_INCLUDED_COLUMN));

                        // add to the list
                        index.IndexedColumns.Add(indexedColumn);
                    }
                }
            }

            ViewFullTextIndexSelectSql viewFullTextIndexSelectSql = new ViewFullTextIndexSelectSql();

            // set attributes
            viewFullTextIndexSelectSql.AddObject(new { Name = name, Schema = schemaName });

            using (SqlCommandHelper sqlCommandHelper = SqlCommandHelper.FetchSqlCommand(this._database.SqlConnection, viewFullTextIndexSelectSql.Render()))
            {
                using (SqlDataReader sqlDataReader = sqlCommandHelper.ExecuteReader())
                {
                    while (sqlDataReader.Read())
                    {
                        View view = views.Find(value =>
                            value.Name == sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_VIEW)) &&
                            value.Schema == sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_SCHEMA)));

                        // should it be created
                        if (view.FullTextIndex == null)
                        {
                            // create it
                            FullTextIndex fullTextIndex = new FullTextIndex();

                            // set attributes
                            fullTextIndex.CatalogName = sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_CATALOG));
                            fullTextIndex.UniqueIndexName = sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_INDEX));

                            // add it
                            view.FullTextIndex = fullTextIndex;
                        }

                        FullTextIndexColumn fullTextIndexColumn = new FullTextIndexColumn(
                            sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_COLUMN)));

                        // add to the list
                        view.FullTextIndex.IndexedColumns.Add(fullTextIndexColumn);
                    }
                }
            }

            // retun the list
            return views;
        }
    }
}
